﻿using MDReader.Helper;
using MDReader.Services;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace MDReader.Control
{
    public partial class CtrlEditor : UserControl
    {
        public CtrlEditor()
        {
            InitializeComponent();
            me = new ME();
            me.getTxtSource = () => { return this.txtSource; };
            me.getMyself = () => { return this; };
        }
        private ILog? logger;
        private IToolstripService? toolstripService;
        public string Content
        {
            get
            {
                return txtSource.Text;
            }
            set
            {
                if (txtSource.Text != value)
                {
                    txtSource.Text = value;
                }
                else
                {
                    TxtSource_VScroll(this, new EventArgs());
                }
            }
        }
        public event EventHandler? Accepted;
        public event EventHandler? Canceled;
        public event EventHandler? Pasted;
        public event EventHandler? Toolstripped;
        public event EventHandler<SyncArgs>? SyncBrowserToOutline;
        private int ReceivedCounts = 0;
        private bool IsBusy = false;
        private bool IsPasting = false;
        private ICtrlEditorResource me;
        public class SyncArgs : EventArgs
        {
            public SyncArgs() { }
            public SyncArgs(int lineNo) { firstVisibleLine = lineNo; }
            public int firstVisibleLine { get; private set; } = -1;
        }
        public void Initalize(ILog log, IToolstripService toolstrip) 
        {
            logger = log; 
            toolstripService = toolstrip;
            toolstripService.Toolstripped += this.Toolstripped;
            toolstripService.Resource = me;
            toolStrip1.Items.AddRange(toolstripService.MakeTools());
        }
        internal void ScrollToCaret(OutlineItem outlineItem)
        {
            try
            {
                int line = outlineItem.LineNumber - 1;
                if (line < 0) { line = 0; }
                int charIndex = txtSource.GetFirstCharIndexFromLine(line);
                if (txtSource.SelectionStart != charIndex && charIndex >= 0)
                {
                    txtSource.SelectionStart = charIndex;
                    txtSource.ScrollToCaret();
                }
            }
            catch (Exception ex)
            {
                if (logger != null) logger.WriteExceptionToEventLog(ex);
            }

            #region 仅最后一次真正进行处理
            ReceivedCounts++;
            int CurrentCount = ReceivedCounts;
            System.Threading.ThreadStart ts = new ThreadStart(new Action(() =>
            {
                System.Threading.Thread.Sleep(250);
                this.Invoke(() =>
                {
                    if (CurrentCount == ReceivedCounts)
                    {
                        ReceivedCounts = 0;
                        IsBusy = false;
                    }
                });
            }));
            System.Threading.Thread t = new Thread(ts);
            t.IsBackground = true;
            t.Start();
            #endregion
        }

        private void btnAccept_Click(object sender, EventArgs e)
        {
            if (Accepted != null)
                Accepted(sender, e);
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            if (Canceled != null)
                Canceled(sender, e);
        }

        private void TxtSource_VScroll(object sender, EventArgs e)
        {
            IsBusy = true;
            int firstVisibleLine = txtSource.GetLineFromCharIndex(txtSource.GetCharIndexFromPosition(new Point(0, 0)));
            SyncArgs a = new SyncArgs(firstVisibleLine);
            if (SyncBrowserToOutline != null)
                SyncBrowserToOutline(txtSource, a);
        }

        private void txtSource_KeyDown(object sender, KeyEventArgs e)
        {
            // 检查是否按下了Ctrl+V（粘贴快捷键）
            if (e.Control && e.KeyCode == Keys.V)
            {
                // 获取剪贴板中的文本
                string clipboardText = Clipboard.GetText();
                if (!string.IsNullOrEmpty(clipboardText))
                {
                    IsPasting = true; // 在粘贴流程中，将会触发粘贴事件

                    #region \t表格转为md表格
                    {
                        string[] lines = clipboardText.Split(System.Environment.NewLine);
                        if (lines.Length > 1 && clipboardText.Contains("\t"))
                        {
                            int MaxColumnCount = 0;
                            Dictionary<int, int> HistoryColumnCount = new Dictionary<int, int>();
                            for (int i = 0; i < lines.Length; i++)
                            {
                                int LocalColumnCount = lines[i].Split('\t').Length;
                                if (LocalColumnCount > MaxColumnCount)
                                    MaxColumnCount = LocalColumnCount;
                                if (!HistoryColumnCount.ContainsKey(LocalColumnCount))
                                {
                                    HistoryColumnCount.Add(LocalColumnCount, 1);
                                }
                                else
                                {
                                    HistoryColumnCount[LocalColumnCount] += 1;
                                }
                            }

                            //if (diffCount <= 3 && ColumnsCount > 0)
                            if (HistoryColumnCount.Count <= 5)
                            {
                                lock (txtSource)
                                {

                                    try
                                    {
                                        using (Graphics g = txtSource.CreateGraphics())
                                        {
                                            int[]? maxColumnWidths = null;
                                            try
                                            {
                                                string[][] cells = lines.Select(line => line.Split('\t')).ToArray();
                                                // 计算每列的最大宽度
                                                maxColumnWidths = new int[cells[0].Length];
                                                //foreach (var row in cells)
                                                //{
                                                //    for (int i = 0; i < row.Length; i++)
                                                //    {
                                                //        maxColumnWidths[i] = Math.Max(maxColumnWidths[i], row[i].Length);
                                                //    }
                                                //}
                                                for (int col = 0; col < maxColumnWidths.Length; col++)
                                                {
                                                    foreach (var row in cells)
                                                    {
                                                        if (col < row.Length)
                                                        {
                                                            SizeF size = TextRenderer.MeasureText(g, row[col], txtSource.Font);
                                                            maxColumnWidths[col] = Math.Max(maxColumnWidths[col], (int)size.Width);
                                                        }
                                                    }
                                                }
                                            }
                                            catch (Exception ex)
                                            { logger?.WriteExceptionToEventLog(ex); }
                                            StringBuilder sb = new StringBuilder();

                                            // 标题行
                                            {
                                                string line = lines[0].Replace("\t", "|");
                                                if (maxColumnWidths != null)
                                                {
                                                    string[] cells = lines[0].Split("\t");
                                                    //line = string.Join(" | ", cells.Select((cell, index) =>
                                                    //cell.PadRight(maxColumnWidths[index])));

                                                    line = "|" + string.Join(" | ", cells.Select((cell, index) =>
                                                    {
                                                        int padding = maxColumnWidths[index] - TextRenderer.MeasureText(g, cell, txtSource.Font).Width;
                                                        return cell + new string(' ', 3 * padding / TextRenderer.MeasureText(g, " ", txtSource.Font).Width);
                                                    })) + "|";
                                                }
                                                sb.Append(line);
                                            }

                                            // 分隔
                                            sb.Append(System.Environment.NewLine);
                                            for (int index = 0; index < MaxColumnCount; index++)
                                            {
                                                string cell = "|";
                                                if (maxColumnWidths != null)
                                                {
                                                    //cell = cell.PadRight(maxColumnWidths[index]);
                                                    int padding = maxColumnWidths[index];
                                                    cell = cell + new string('-', 5 * padding / TextRenderer.MeasureText(g, " ", txtSource.Font).Width / 2);
                                                }
                                                sb.Append(cell);
                                            }
                                            sb.Append("|");
                                            // 生成表格
                                            for (int i = 1; i < lines.Length; i++)
                                            {
                                                if (string.IsNullOrEmpty(lines[i]))
                                                    continue;
                                                sb.Append(System.Environment.NewLine);
                                                // 将\t替换为|
                                                {
                                                    string line = lines[i].Replace("\t", "|");
                                                    if (maxColumnWidths != null)
                                                    {
                                                        string[] cells = lines[i].Split("\t");
                                                        //line = string.Join(" | ", cells.Select((cell, index) =>
                                                        //cell.PadRight(maxColumnWidths[index])));
                                                        line = "|" + string.Join(" | ", cells.Select((cell, index) =>
                                                        {
                                                            int padding = maxColumnWidths[index] - TextRenderer.MeasureText(g, cell, txtSource.Font).Width;
                                                            return cell + new string(' ', 3 * padding / TextRenderer.MeasureText(g, " ", txtSource.Font).Width);
                                                        })) + "|";
                                                    }
                                                    sb.Append(line);
                                                }
                                            }
                                            string processedText = sb.ToString();
                                            Clipboard.SetText(processedText);
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        if (logger != null) logger.WriteExceptionToEventLog(ex);
                                    }
                                }
                            }
                        }
                    }
                    #endregion
                }
            }
        }

        private void txtSource_TextChanged(object sender, EventArgs e)
        {
            if (IsPasting && Pasted != null)
                Pasted(sender, e);
            IsPasting = false;
        }

        private void txtSource_MultilineChanged(object sender, EventArgs e)
        {
            IsPasting = false;
        }

        private void txtSource_Validated(object sender, EventArgs e)
        {
            IsPasting = false;
        }

        private class ME : ICtrlEditorResource
        {
            public Func<RichTextBox>? getTxtSource { get; set; }
            public Func<CtrlEditor>? getMyself { get; set; }
        }
    }
    
    public interface ICtrlEditorResource : MDReader.Extension.IResource
    {
        Func<RichTextBox>? getTxtSource { get; set; }
        Func<CtrlEditor>? getMyself { get; set; }
    }
}
